package twel.probenprophet.swing.ui;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ResourceBundle;

import javax.enterprise.event.Observes;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JSeparator;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.BevelBorder;

import org.slf4j.Logger;

import twel.probenprophet.domain.event.StatusBarEvent;
import twel.probenprophet.swing.ui.panels.CheckProbabilityPanel;
import twel.probenprophet.swing.ui.panels.SpellCheckPanel;

@Singleton
public class ProbenprophetFrame extends JFrame {

	private static final String CHECK_PROBABILITY_ID = "checkProbability";
	private static final String SPELL_CHECK_ID = "spellCheck";

	private static final long serialVersionUID = 1L;

	private final ResourceBundle resourceBundle = ResourceBundle.getBundle("i18n/ProbenprophetFrame");

	@Inject
	private Logger logger;
	@Inject
	private CheckProbabilityPanel checkProbabilityPanel;
	@Inject
	private SpellCheckPanel spellCheckPanel;

	private JLabel statusLabel;
	private JPanel contentPanel;

	void init() {
		getContentPane().setLayout(new BorderLayout());
		getContentPane().add(createContentPanel(), BorderLayout.CENTER);
		getContentPane().add(createStatusPanel(), BorderLayout.SOUTH);

		setJMenuBar(createMenu());
		setDefaultCloseOperation(EXIT_ON_CLOSE);

		setSystemLookAndFeel();

		pack();
		setMinimumSize(getSize());
		setVisible(true);
	}

	private JPanel createContentPanel() {
		contentPanel = new JPanel(new CardLayout());

		contentPanel.add(spellCheckPanel, SPELL_CHECK_ID);
		contentPanel.add(checkProbabilityPanel, CHECK_PROBABILITY_ID);

		return contentPanel;
	}

	private JPanel createStatusPanel() {
		JPanel statusPanel = new JPanel();
		statusPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED),
				BorderFactory.createEmptyBorder(0, 4, 0, 4)));
		statusPanel.setLayout(new BoxLayout(statusPanel, BoxLayout.X_AXIS));
		statusPanel.setPreferredSize(new Dimension(getWidth(), 18));

		statusLabel = new JLabel(resourceBundle.getString("welcomeMessage"));
		statusLabel.setHorizontalAlignment(SwingConstants.LEFT);
		statusPanel.add(statusLabel);

		return statusPanel;
	}

	private JMenuBar createMenu() {
		JMenuBar menuBar = new JMenuBar();

		menuBar.add(createProgramMenu());

		return menuBar;
	}

	private JMenu createProgramMenu() {
		ButtonGroup panelSelectionGroup = new ButtonGroup();

		JRadioButtonMenuItem spellCheckItem = getPanelSwitchingMenuItem(SPELL_CHECK_ID, panelSelectionGroup);
		spellCheckItem.setSelected(true);

		JRadioButtonMenuItem checkProbabilityItem = getPanelSwitchingMenuItem(CHECK_PROBABILITY_ID, panelSelectionGroup);

		JMenuItem exitItem = new JMenuItem(resourceBundle.getString("quit"));
		exitItem.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				dispose();
				System.exit(0);
			}
		});

		JMenu programMenu = new JMenu(resourceBundle.getString("program"));
		programMenu.add(checkProbabilityItem);
		programMenu.add(spellCheckItem);
		programMenu.add(new JSeparator());
		programMenu.add(exitItem);

		return programMenu;
	}

	private JRadioButtonMenuItem getPanelSwitchingMenuItem(final String panelId, ButtonGroup buttonGroup) {
		JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(resourceBundle.getString(panelId));
		buttonGroup.add(menuItem);
		menuItem.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				switchToPanel(panelId);
				setStatusMessage("");
			}

			private void switchToPanel(final String panelId) {
				CardLayout cardLayout = (CardLayout) (contentPanel.getLayout());
				cardLayout.show(contentPanel, panelId);
			}
		});
		return menuItem;
	}

	private void setSystemLookAndFeel() {
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
			SwingUtilities.updateComponentTreeUI(this);
		} catch (ClassNotFoundException e) {
			logAndIgnore(e);
		} catch (InstantiationException e) {
			logAndIgnore(e);
		} catch (IllegalAccessException e) {
			logAndIgnore(e);
		} catch (UnsupportedLookAndFeelException e) {
			logAndIgnore(e);
		}
	}

	private void logAndIgnore(Exception e) {
		logger.warn(e.getMessage(), e);
	}

	public void setStatusMessage(@Observes StatusBarEvent event) {
		final String message = event.getMessage();
		setStatusMessage(message);
	}

	private void setStatusMessage(final String message) {
		EventQueue.invokeLater(new Runnable() {

			@Override
			public void run() {
				statusLabel.setText(message);
				statusLabel.repaint();
			}
		});
	}
}
